package io.gitee.chearnee.fw.common.component.converter;

import io.gitee.chearnee.fw.common.model.IBaseEnum;
import io.gitee.chearnee.fw.common.utils.JacksonEnumUtils;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.Iterator;

/**
 * RequestParam PathVariable 的反序列化
 *
 * @author cn
 * @version 1.0
 * @description
 * @date 2022/5/10 15:09
 * @see org.springframework.web.bind.annotation.PathVariable
 * @see org.springframework.web.bind.annotation.RequestParam
 */
public class StringToBaseEnumConverterFactory implements

        ConverterFactory<String, IBaseEnum<?>> {
  @Override
  public <T extends IBaseEnum<?>> Converter<String, T> getConverter(Class<T> targetType) {
    return new StringToBaseEnum<>(targetType);
  }

  private static class StringToBaseEnum<T extends IBaseEnum<?>> implements Converter<String, T> {

    private final Class<T> enumType;

    StringToBaseEnum(Class<T> enumType) {
      this.enumType = enumType;
    }

    @Override
    @Nullable
    public T convert(String source) {
      if (!StringUtils.hasText(source)) {
        // It's an empty enum identifier: reset the enum value to null.
        return null;
      }
      IBaseEnum<?> fieldCache = JacksonEnumUtils.getFieldCache(enumType, source);
      if (fieldCache != null) {
        return (T) fieldCache;
      }
      Iterator<T> iterator = Arrays.stream(enumType.getEnumConstants()).iterator();
      while (iterator.hasNext()) {
        T next = iterator.next();
        if (next.getValue().toString().equals(source)) {
          return next;
        }
      }
      return null;
    }
  }
}
